﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using PS3Helpers.Helpers;

namespace PS3Helpers
{
    public class VirtualFile
    {
        internal VirtualDirectory _ownerDirectory = null;
        private string _name;
        private bool _locked;
        private string _sourceFilename;
        private string _relativeFilename;

        public VirtualFile(string sourcefilename)
            : this(Path.GetFileName(sourcefilename), false, sourcefilename, null)
        {
        }

        public VirtualFile(string name, string sourcefilename, string relativefilename)
            : this(name, false, sourcefilename, relativefilename)
        {
        }

        internal VirtualFile(string name, bool locked, string sourcefilename, string relativefilename)
        {
            if (string.IsNullOrEmpty(name))
                throw new Exception("Name can't be an empty string!");

            _name = name;
            _locked = locked;
            _sourceFilename = sourcefilename;
            _relativeFilename = relativefilename;
        }

        // Clone the VirtualFile object
        public VirtualFile(VirtualFile source)
        {
            _name = source._name;
            _sourceFilename = source._sourceFilename;
            _locked = source._locked;
        }

        public string Name
        {
            get { return _name; }
            internal set { _name = value; }
        }

        public string SourceFilename
        {
            get
            {
                PS3PackageFile pf = GetPackageFile();
                if (
                     (pf != null) &&
                     (!string.IsNullOrEmpty(pf.Filename)) &&
                     (!File.Exists(_sourceFilename))
                   )
                {
                    // Try to locate the correct filename...
                    string newpath = Path.Combine(Path.GetDirectoryName(pf.Filename), _relativeFilename);
                    if (File.Exists(newpath))
                    {
                        return newpath;
                    }
                }
                
                return _sourceFilename;
            }
            set { _sourceFilename = value; }
        }

        public bool Locked
        {
            get { return _locked; }
        }

        internal PS3PackageFile GetPackageFile()
        {
            if (_ownerDirectory != null)
                return _ownerDirectory.GetPackageFile();

            return null;
        }

        public string GetRelativePath()
        {
            PS3PackageFile pf = GetPackageFile();
            if (pf == null)
                return "";

            return GetRelativePath(pf.Filename);
        }

        public string GetRelativePath(string basepath)
        {
            return RelativePath.GetRelativePath(basepath, _sourceFilename);
        }
    }

    public class VirtualFileCollection : ListWithChangedEvent<VirtualFile>
    {
        private VirtualDirectory _owner = null;

        internal VirtualFileCollection(VirtualDirectory owner)
        {
            _owner = owner;
        }

        public VirtualFileCollection()
        {
        }

        protected override void OnChanged(ListWithChangedEventType changetype, VirtualFile element)
        {
            base.OnChanged(changetype, element);

            switch (changetype)
            {
                case ListWithChangedEventType.Add:
                case ListWithChangedEventType.Insert:
                    {
                        lock (element)
                        {
                            if ((element._ownerDirectory != null) && (element._ownerDirectory != _owner))
                            {
                                base.Remove(element);
                                throw new Exception("Item already exists in another collection!");
                            }

                            element._ownerDirectory = _owner;
                        }
                        break;
                    }
                case ListWithChangedEventType.Remove:
                    {
                        lock (element)
                        {
                            if (element._ownerDirectory == _owner)
                            {
                                element._ownerDirectory = null;
                            }
                        }

                        break;
                    }
            }
        }
    }
}
